#include <memoire.h>
#include <ecrantexte.h>

void* gAdresseLaPlusBasse;
void* gAdresseLaPlusHaute;

int test_CopierBlocMemoire() {
  int testreussi = 1;
  char testrate = ' ';

  if(test_CopierBlocMemoire_BlocSimple() == 0)
  {
    testreussi = 0; testrate = 'a';
  }
  else if(test_CopierBlocMemoire_BlocVide() == 0)
  {
    testreussi = 0; testrate = 'b';
  }
  else if(test_CopierBlocMemoire_DebutBlocDestinationDansBlocSource() == 0)
  {
    testreussi = 0; testrate = 'c';
  }

  if(testreussi == 0)
  {
    unsigned char* ptrecran = (unsigned char*)(0xB8000 + 160);
    *ptrecran = 'M';
    ptrecran += 2;
    *ptrecran = 'e';
    ptrecran += 2;
    *ptrecran = 'm';
    ptrecran += 4;
    *ptrecran = 'P';
    ptrecran += 2;
    *ptrecran = 'r';
    ptrecran += 2;
    *ptrecran = 'o';
    ptrecran += 2;
    *ptrecran = 'b';
    ptrecran += 4;
    *ptrecran = testrate;
  }

  return testreussi;
}

int test_CopierBlocMemoire_BlocSimple()
{
  int a, b;
  a = 0x11223344;
  b = 0x55667788;

  CopierBlocMemoire(&a, &b, sizeof(int));

  if(b == 0x11223344)
  {
    return 1;
  }
  else
  {
    return 0;
  }
}

int test_CopierBlocMemoire_BlocVide()
{
  int a, b;

  a = 0x11223344;
  b = 0x55667788;

  CopierBlocMemoire(&a, &b, 0);

  if(a == 0x11223344 && b == 0x55667788)
  {
    return 1;
  }
  else
  {
    return 0;
  }
}

int test_CopierBlocMemoire_DebutBlocDestinationDansBlocSource()
{
  char tableau[5] = {'a', 'b', 'c', 'd', 'e'};

  CopierBlocMemoire(&tableau[0], &tableau[2], 3);

  if(tableau[0] == 'a' && tableau[1] == 'b' && tableau[2] == 'a' && tableau[3] == 'b' && tableau[4] == 'c')
  {
    return 1;
  }
  else
  {
    return 0;
  }
}

int CopierBlocMemoire(void* source, void* destination, int taille)
{
  if(CalculerTailleRecouvrementBlocADroite(source, destination, taille) > 0)
  {
    return CopierBlocMemoireSensCopieInverse(source, destination, taille);
  }

  unsigned char* destinationcaractere = (unsigned char*)destination;
  unsigned char* sourcecaractere = (unsigned char*)source;

  for(;taille>0;taille--)
  {
    *destinationcaractere = *sourcecaractere;
    destinationcaractere++;
    sourcecaractere++;
  }
}

int CopierBlocMemoireSensCopieInverse(void* source, void* destination, int taille) {
  unsigned char* destinationcaractere = (unsigned char*)((int)destination + taille - 1);
  unsigned char* sourcecaractere = (unsigned char*)((int)source + taille - 1);

  for(;taille>0;taille--)
  {
    *destinationcaractere = *sourcecaractere;
    destinationcaractere--;
    sourcecaractere--;
  }
}

int CalculerTailleRecouvrementBlocADroite(void* blocgauche, void* blocdroit, int tailleblocgauche)
{
  int taillerecouvrement;
  void* finblocgauche;

  finblocgauche = (void*)((int)blocgauche + tailleblocgauche);
  taillerecouvrement = (int)finblocgauche - (int)blocdroit;

  if(taillerecouvrement < 0)
  {
    return 0;
  }

  return taillerecouvrement;
}

/************************************/

unsigned int RecupererTailleRam(void* mbootstructuredinfo)
{
  int* structure = (int*)mbootstructuredinfo;

  if(structure[0] % 2 == 1)
  {
    if(structure[1] <= structure[2])
    {
      gAdresseLaPlusBasse = (void*)structure[1];
      gAdresseLaPlusHaute = (void*)structure[2];
      return structure[2] - structure[1];
    }
  }

  gAdresseLaPlusBasse = 0;
  gAdresseLaPlusHaute = 0;
  return 0;
}

int test_RecupererTailleRam(EcranTexte* ecrantemporaire)
{
  int testreussi = 1;

  if(test_RecupererTailleRam_InfoNonContenueDansLaStructure() == 0)
  {
    ecrantemporaire->Ecrire("Test de la fonction RecupererTailleRam() avec une structure ne contenant pas\nl'information rate.\n");
    testreussi = 0;
  }
  else if(test_RecupererTailleRam_StructureNormale() == 0)
  {
    ecrantemporaire->Ecrire("Test de la fonction RecupererTailleRam() avec une structure normale rate.\n");
    testreussi = 0;
  }
  else if(test_RecupererTailleRam_InformationsInvalides() == 0)
  {
    ecrantemporaire->Ecrire("Test de la fonction RecupererTailleRam() avec une structure invalide rate.\n");
    testreussi = 0;
  }

  return testreussi;
}

int test_RecupererTailleRam_InfoNonContenueDansLaStructure()
{
  int structure[3] = {0xFEDCBA98, 865, 78999};
  int taillerenseignee;

  taillerenseignee = RecupererTailleRam(structure);

  if(taillerenseignee != 0 || gAdresseLaPlusBasse != 0 || gAdresseLaPlusHaute != 0)
  {
    return 0;
  }
  else
  {
    return 1;
  }
}

int test_RecupererTailleRam_StructureNormale()
{
  int structure[3] = {0x7471, 0x1000, 0x1FFFF};
  int taillerenseignee;

  taillerenseignee = RecupererTailleRam(structure);

  if(taillerenseignee == (0x1FFFF - 0x1000))
  {
    return 1;
  }
  else
  {
    return 0;
  }
}

int test_RecupererTailleRam_InformationsInvalides()
{
  int structure[3] = {3, 0x1FFFF, 0x1000};
  int taillerenseignee;

  taillerenseignee = RecupererTailleRam(structure);

  if(taillerenseignee != 0)
  {
    return 0;
  }
  else
  {
    return 1;
  }
}
